package wsi.subgraph.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import org.rygh.core.html.table.HtmlTable;
import org.rygh.core.html.table.TableData;
import org.rygh.core.html.table.TableTuple;
import org.rygh.core.model.common.MapList;
import org.rygh.semantic.model.rdf.Entity;

import wsi.dataguide.tree.WSXmlLeaf;
import wsi.match.MatchPair;
import wsi.match.SubtreeMatch;
import wsi.subgraph.tree.EntityLeaf;

public class EntityResolve {

	private final MapList<EntityLeaf, ResolvePair> resolveMapList = new MapList<>();
	private EntityGroupController entityGroupController;

	public EntityResolve() {

	}

	public EntityGroupController getEntityGroupController() {
		return entityGroupController;
	}

	public ResolvePair getPairOfMaxProb(WSXmlLeaf subroot, EntityGroup group) {
		return getPairOfMaxProb(subroot, group.getNodes());
	}

	private ResolvePair getPairOfMaxProb(WSXmlLeaf subroot,
			List<EntityLeaf> nodes) {
		if (nodes.isEmpty())
			return null;

		ResolvePair pair = null;
		double pred = -1;

		for (EntityLeaf n : nodes) {
			// y:wordnet_
			if (!resolveMapList.containsKey(n))
				continue;

			List<ResolvePair> pairs = resolveMapList.get(n);

			for (ResolvePair p : pairs) {
				if (p.getXmlLeaf() != subroot)
					continue;

				if (pred < p.getProbability()) {
					pred = p.getProbability();
					pair = p;
				}
			}
		}

		return pair;
		// 131016 do not prune, otherwise, we may obtain nothing.
		// return pred > MatchProperty.Threshold.MAJORITY ? pair : null;
	}

	public ResolvePair getPairOfMaxProbWithOppositeMatch(WSXmlLeaf subroot,
			EntityGroup group, SubtreeMatch subtreeMatch) {
		List<EntityLeaf> nodes = new ArrayList<>();

		// EntityNode inputNode = entityGroupController.getInputEntity();
		EntityLeaf node;

		for (EntityLeaf n : group.getNodes()) {
			// y:wordnet_
			if (!resolveMapList.containsKey(n))
				continue;

			boolean childOf = false;

			// check whether there are any opposite match w.r.t. n as the
			// targeted node.
			for (MatchPair pair : subtreeMatch.getMatchPairs()) {
				node = pair.getEntityLeaf();
				childOf |= node.isChildOf(n);
			}

			if (childOf)
				nodes.add(n);
		}

		{
			// if (!nodes.isEmpty()) {
			// System.out.printf(
			// "Input %s, Subtree %s has potential match \n\t%s.\n",
			// subroot.getValue().getValue(), subroot.getXpath()
			// .getValue(), nodes);
			// }

			if (nodes.isEmpty()) {
				// System.out.printf("No opposite match for %s @ %s\n", subroot
				// .getValue().getValue(), subroot.getXpath());
			}
		}

		return getPairOfMaxProb(subroot, nodes);
	}

	public List<ResolvePair> getResolvePairs(EntityLeaf node) {
		return resolveMapList.get(node);
	}

	public void put(EntityLeaf node, ResolvePair pair) {
		resolveMapList.put(node, pair);
	}

	public void setEntityGroupController(
			EntityGroupController entityGroupController) {
		this.entityGroupController = entityGroupController;
	}

	public HtmlTable toHtmlTable() {
		TableData data = new TableData();
		TableTuple tuple = new TableTuple();

		tuple.add("Distance", "Predicate Path", "Entity", "Subroot",
				"Probability");
		data.add(tuple);

		for (Entry<Integer, List<EntityGroup>> e : entityGroupController
				.getGroupMapList().entrySet()) {

			for (EntityGroup g : e.getValue()) {

				for (EntityLeaf n : g.getNodes()) {
					Entity entity = n.getValue().getValue();

					if (!resolveMapList.containsKey(n))
						continue;

					List<ResolvePair> pairs = resolveMapList.get(n);

					for (ResolvePair p : pairs) {
						tuple = new TableTuple();
						tuple.add(e.getKey());
						tuple.add(String.format("%s (%d)", g.getKey(), g
								.getNodes().size()));
						tuple.add(entity.getValue());
						tuple.add(p.getXmlLeaf().getXpath().toString());
						tuple.add(String.format("%.4f", p.getValue()));

						data.add(tuple);
					}
				}
			}
		}

		return new HtmlTable("Entity Grouping", data, false);
	}
}
